#pragma once
#define NOMINMAX
#include <vector>
#include <string>
#include <ncnn/net.h>

namespace onechchy
{
	struct Bbox
	{
		float score;
		int x1;
		int y1;
		int x2;
		int y2;
		float area;
		float ppoint[10];
		float regreCoord[4];
	};
	
	class MTCNN
	{
	public:
		MTCNN(const std::string& model_path);
		MTCNN(const std::vector<std::string> paramFiles, const std::vector<std::string> binFiles);
		~MTCNN();

		bool loadResult();
		void setMinFaceSize(int minSize);
		void detect(ncnn::Mat& img, std::vector<Bbox>& faces);
		void detectMaxFace(ncnn::Mat& img, std::vector<Bbox>& finalBbox);

	protected:
		void PNet();
		void PNet(float scale);
		void RNet();
		void ONet();
		void generateBbox(ncnn::Mat score, ncnn::Mat location, std::vector<Bbox>& boundingBox, float scale);
		void nms(std::vector<Bbox>& boundingBox, const float overlap_threshold, std::string modelname = "Union");
		void refine(std::vector<Bbox>& vecBbox, const int& height, const int& width, bool square);
		void extractMaxFace(std::vector<Bbox>& boundingBox);
		void nmsTwoBoxs(std::vector<Bbox>& boundingBox, std::vector<Bbox>& previousBox, const float overlapThreshold, std::string modelname = "Union");

	private:
		ncnn::Net pNet, rNet, oNet;
		ncnn::Mat mImg;
		std::vector<Bbox> mFirPreviousBbox, mSecPreviousBbox, mThirdPreviouBbox;
		std::vector<Bbox> mFirBbox, mSecBbox, mThirdBbox;
		int mImgW, mImgH;

	private:
		bool mLoadResult = false;
		int mMinFaceSize = 40;
		const float mThreshold[3] = { 0.8f, 0.8f, 0.6f };
		const float mPreFactor = 0.709f;
	};
	
}

